//
// Created on 2025/1/13.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".

#include "DrawTesting.h"
#include <algorithm>
#include <codecvt>
#include <locale>
#include <multimedia/image_framework/image_pixel_map_mdk.h>
#include <native_drawing/drawing_canvas.h>
#include <native_drawing/drawing_color.h>
#include <native_drawing/drawing_path.h>
#include <native_drawing/drawing_pen.h>
#include <native_drawing/drawing_rect.h>
#include <native_drawing/drawing_round_rect.h>
#include <native_drawing/drawing_sampling_options.h>
#include <native_drawing/drawing_text_typography.h>
#include <native_drawing/drawing_font_collection.h>
#include <native_drawing/drawing_pixel_map.h>

#include <multimedia/image_framework/image/image_source_native.h>
#include <multimedia/image_framework/image/pixelmap_native.h>

#include <random>

#include "utils/log.h"


static char32_t generateRandomChineseChar() {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(0x4e00, 0x9fff);
    return static_cast<char32_t>(dis(gen));
}

// 生成指定长度的随机汉字字符串
static std::string generateRandomChineseString(int length) {
    std::string result;
    std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> converter;
    for (int i = 0; i < length; ++i) {
        char32_t randomChar = generateRandomChineseChar();
        std::u32string temp(1, randomChar);
        result += converter.to_bytes(temp);
    }
    return result;
}


DrawTesting::DrawTesting() {
    font_collection = OH_Drawing_CreateSharedFontCollection();
    all_strings = std::vector<std::string>();
}

DrawTesting::~DrawTesting() {
    OH_Drawing_DestroyFontCollection(font_collection);
    this->font_collection = nullptr;
    for (auto pixelmap : all_pixelmaps_image) {
        OH_Drawing_PixelMapDissolve(pixelmap);
    }
}


void DrawTesting::SetDrawCanvas(OH_Drawing_Canvas *canvas) { this->canvas = canvas; }

void DrawTesting::DrawList(float x, float y, float width, float height, const char *string,
                           OH_Drawing_PixelMap *pixelmap) {
    int pic_x = x;
    int text_x = x + height;
    int rect_x = x + width - height;
    this->DrawPicture(pic_x, y, height, height, pixelmap);
    this->DrawText(text_x, y, width - height * 2, string);

    auto pen = OH_Drawing_PenCreate();
    OH_Drawing_PenSetWidth(pen, 5);
    OH_Drawing_PenSetColor(pen, OH_Drawing_ColorSetArgb(0xFF, 0xFF, 0x00, 0x00));
    OH_Drawing_CanvasAttachPen(canvas, pen);

    OH_Drawing_Rect *rect = OH_Drawing_RectCreate(rect_x, y, rect_x + height, y + height);

    OH_Drawing_RoundRect *round_rect = OH_Drawing_RoundRectCreate(rect, 30, 20);

    OH_Drawing_CanvasDrawRoundRect(canvas, round_rect);

    OH_Drawing_RectDestroy(rect);
    OH_Drawing_RoundRectDestroy(round_rect);
    OH_Drawing_CanvasDetachPen(canvas);
    OH_Drawing_PenDestroy(pen);
}

void DrawTesting::DrawPicture(float x, float y, float width, float height, OH_Drawing_PixelMap *pixelmap) {
    auto path = OH_Drawing_PathCreate();
    OH_Drawing_PathAddCircle(path, x, y, fmin(width, height) / 2, OH_Drawing_PathDirection::PATH_DIRECTION_CW);
    OH_Drawing_Rect *pixel_dst_rect = OH_Drawing_RectCreate(x, y, x + width, y + height);
    OH_Drawing_SamplingOptions *sample_options = OH_Drawing_SamplingOptionsCreate(
        OH_Drawing_FilterMode::FILTER_MODE_LINEAR, OH_Drawing_MipmapMode::MIPMAP_MODE_LINEAR);

    if (pixelmap) {
        OH_Drawing_CanvasDrawPixelMapRect(this->canvas, pixelmap, nullptr, pixel_dst_rect, sample_options);
//         LOGI("draw pixelmap %{public}x", pixelmap);
    } else {
        LOGI("pixelmap is null");
    }

    OH_Drawing_RectDestroy(pixel_dst_rect);
    OH_Drawing_SamplingOptionsDestroy(sample_options);
}

void DrawTesting::DrawText(float x, float y, float max_width, const char *string) {
    // 创建排版样式
    OH_Drawing_TypographyStyle *style = OH_Drawing_CreateTypographyStyle();
    OH_Drawing_SetTypographyTextDirection(style, TEXT_DIRECTION_LTR);
    OH_Drawing_SetTypographyTextAlign(style, TEXT_ALIGN_LEFT);
    OH_Drawing_SetTypographyTextMaxLines(style, 5);

    // 创建文本样式
    OH_Drawing_TextStyle *textStyle = OH_Drawing_CreateTextStyle();
    OH_Drawing_SetTextStyleFontSize(textStyle, 40.0);
    OH_Drawing_SetTextStyleColor(textStyle, 0xFF0000FF); // 蓝色

    // 创建排版处理器
    OH_Drawing_TypographyCreate *create = OH_Drawing_CreateTypographyHandler(style, this->font_collection);
    OH_Drawing_TypographyHandlerPushTextStyle(create, textStyle);
    OH_Drawing_TypographyHandlerAddText(create, string);

    // 创建排版对象并进行排版和绘制
    OH_Drawing_Typography *typography = OH_Drawing_CreateTypography(create);
    OH_Drawing_TypographyLayout(typography, max_width);
    OH_Drawing_TypographyPaint(typography, canvas, x, y);

    // 释放资源
    OH_Drawing_DestroyTypography(typography);
    OH_Drawing_DestroyTypographyHandler(create);
    OH_Drawing_DestroyTextStyle(textStyle);
    OH_Drawing_DestroyTypographyStyle(style);
}

void DrawTesting::DrawLists(float x, float y, float width, float height, int num) {
    int list_height = height / num - 20;

    OH_Drawing_CanvasClear(this->canvas, 0xffffffff);

    int max_num = (abs(nowY + y) + height) / (height / num);
    for (int i = 0; i < max_num + 10; i++) {
        int real_y = nowY + y + (list_height + 20) * i;
        int pic_index = 0;
        OH_Drawing_PixelMap *pixelmap = nullptr;
        if (all_pixelmaps_image.size() > 0) {
            pic_index = i % all_pixelmaps_image.size();
            pixelmap = all_pixelmaps_image[pic_index];
        }
        if (real_y > -list_height && real_y < height) {
            this->DrawList(x, real_y, width, list_height, GetIndexString(i).c_str(), pixelmap);
        }
    }
}

std::string DrawTesting::GetIndexString(int index) {
    if (index < 0) {
        return "error";
    }
    if (all_strings.size() < index + 1) {
        all_strings.push_back(generateRandomChineseString(20));
    }
    return all_strings[index];
}


void DrawTesting::TouchMove(int touchType, int x, int y) {
    if (touchType == 0) {
        lastY = y;
    } else if (touchType == 1) {
        nowY -= lastY - y;
        lastY = y;
    } else if (touchType == 2) {
    }
}

void DrawTesting::AddPixelmap(NativePixelMap *pixelmap) {
    all_pixelmaps.push_back(pixelmap);
    OH_Drawing_PixelMap *drawing_pixelmap = OH_Drawing_PixelMapGetFromNativePixelMap(pixelmap);
    all_pixelmaps_image.push_back(drawing_pixelmap);
}
